package com.xuecheng.media.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.xuecheng.base.constant.MediaProcessConstant;
import com.xuecheng.media.mapper.MediaFilesMapper;
import com.xuecheng.media.mapper.MediaProcessHistoryMapper;
import com.xuecheng.media.mapper.MediaProcessMapper;
import com.xuecheng.media.model.po.MediaFiles;
import com.xuecheng.media.model.po.MediaProcess;
import com.xuecheng.media.model.po.MediaProcessHistory;
import com.xuecheng.media.service.IMediaProcessService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 勾新杰
 * @since 2025-01-16
 */
@Service
@RequiredArgsConstructor
public class MediaProcessServiceImpl extends ServiceImpl<MediaProcessMapper, MediaProcess> implements IMediaProcessService {

    /**
     * 媒体处理mapper
     */
    private final MediaProcessMapper mediaProcessMapper;

    /**
     * 媒体处理历史mapper
     */
    private final MediaProcessHistoryMapper mediaProcessHistoryMapper;

    /**
     * 媒体文件mapper
     */
    private final MediaFilesMapper mediaFilesMapper;

    /**
     * 根据分片获取待处理任务
     *
     * @param shardIndex 分片索引
     * @param shardTotal 分片总数
     * @param count      要取的总任务数
     * @return 任务列表
     */
    @Override
    public List<MediaProcess> getMediaProcessList(Integer shardIndex, Integer shardTotal, Integer count) {
        return mediaProcessMapper.selectProcessByShardIndex(shardTotal, shardIndex, count, MediaProcessConstant.MAX_FAIL_COUNT);
    }

    /**
     * 启动任务
     *
     * @param id 任务id
     * @return true表示启动成功，false表示启动失败
     */
    @Override
    public boolean startProcess(Long id) {
        return mediaProcessMapper.startProcess(id, MediaProcessConstant.MAX_FAIL_COUNT) > 0;
    }

    /**
     * 标记任务为成功
     *
     * @param id  任务id
     * @param url 文件url
     */
    @Override
    @Transactional
    public void successProcess(Long id, String url) {
        // 1. 更新任务状态为成功
        String filePath = url.split("/", 3)[2];
        MediaProcess mediaProcess = MediaProcess.builder()
                .id(id)
                .filePath(filePath)
                .status(MediaProcessConstant.PROCESS_SUCCESS)
                .finishDate(LocalDateTime.now())
                .build();
        mediaProcessMapper.updateById(mediaProcess);
        // 2. 更新media_files表的fil_path和url字段
        mediaProcess = mediaProcessMapper.selectById(id);
        MediaFiles mediaFiles = MediaFiles.builder()
                .id(mediaProcess.getFileId())
                .filePath(filePath)
                .url(url)
                .build();
        mediaFilesMapper.updateById(mediaFiles);
        // 3. 增加media_process_history表的记录
        mediaProcess = mediaProcessMapper.selectById(id);
        MediaProcessHistory mediaProcessHistory = BeanUtil.copyProperties(mediaProcess, MediaProcessHistory.class);
        mediaProcessHistoryMapper.insert(mediaProcessHistory);
        // 4. 删除media_process表的记录
        mediaProcessMapper.deleteById(id);
    }

    /**
     * 标记任务为失败
     *
     * @param id       任务id
     * @param errorMsg 失败原因
     */
    @Override
    @Transactional
    public void failProcess(Long id, String errorMsg) {
        // 1. 查询该任务
        MediaProcess mediaProcess = mediaProcessMapper.selectById(id);
        // 2. 设置状态为失败，失败原因
        mediaProcess.setStatus(MediaProcessConstant.PROCESS_FAIL);
        mediaProcess.setErrormsg(errorMsg);
        // 3. 删除该任务
        mediaProcessMapper.deleteById(id);
        // 4. 添加到历史表
        MediaProcessHistory mediaProcessHistory = BeanUtil.copyProperties(mediaProcess, MediaProcessHistory.class);
        mediaProcessHistory.setFinishDate(LocalDateTime.now());
        mediaProcessHistoryMapper.insert(mediaProcessHistory);
    }

    /**
     * 自增任务失败次数
     *
     * @param id 任务id
     * @return 任务失败次数
     */
    @Override
    public Integer fail(Long id) {
        MediaProcess select = mediaProcessMapper.selectById(id);
        Integer failCount = select.getFailCount() + 1;
        MediaProcess mediaProcess = MediaProcess.builder()
                .id(id)
                .status(MediaProcessConstant.PROCESS_FAIL)
                .failCount(failCount)
                .build();
        mediaProcessMapper.updateById(mediaProcess);
        return failCount;
    }

    /**
     * 找出超时任务
     *
     * @return 超时任务
     */
    @Override
    public List<MediaProcess> listExceedTimeProcess() {
        return mediaProcessMapper.listExceedTimeProcess(MediaProcessConstant.MAX_PROCESS_TIME);
    }
}
